/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.cxhd.dc.websocket;

import com.baseWebSocket.BaseServer;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.http.HttpRequest;

/**
 *
 * @author Administrator
 */
public class StartServer extends BaseServer {

    public Map<String, WebClient> allUserId = new ConcurrentHashMap<String, WebClient>();
    private Message message = new Message();

    private Gson gson = new Gson();
    private MsgService ms = new MsgService(this);
    private String loginId, clientIp;
    private BlockingQueue sendMessageQueue = new LinkedBlockingQueue<Message>();//发送消息的队列

    private List<WebClient> userList;

    public StartServer(int port) {
        super(port);
    }

    private static StartServer ss;

    public static StartServer getInstance() {
        if (ss == null) {
            ss = new StartServer(11211);
            ss.init();
        }
        return ss;
    }

    public void init() {
        ms.start();
    }

    public void stopSendThread() throws InterruptedException {
        Message msg = new Message();
        ms.setFlag(false);
        msg.setType("closeServer");
        getSendQueue().put(msg);

    }

    @Override
    public void onOpen(ChannelHandlerContext chc, HttpRequest hr) {

        saveUser(chc, hr);

    }

    @Override
    public void onMessage(ChannelHandlerContext chc, String msg) {
        try {
             System.out.println(msg);
            message = gson.fromJson(msg, new TypeToken<Message>() {
            }.getType());
            //  System.out.println(gson.toJson(message));
            getSendQueue().put(message);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void onClose(ChannelHandlerContext chc) {
        for (String loginId : allUserId.keySet()) {
            if (allUserId.get(loginId).getCon() == chc) {

                System.out.println(allUserId.get(loginId).getName() + " 离开了");
                removeUser(loginId);
                // sayToAllOffline(loginId);
                //sayToAll();
                break;
            }
        }

    }

    private void saveUser(ChannelHandlerContext chc, HttpRequest hr) {
        WebClient client = new WebClient();
        loginId = hr.getUri().replace("/", "").split("&")[0];
        String username = hr.getUri().replace("/", "").split("&")[1];
        clientIp = chc.getChannel().getRemoteAddress().toString().split(":")[0];
        clientIp = clientIp.replace("/", "");
        if (clientIp.equals("0")) {
            clientIp = "127.0.0.1";
        }

        if (allUserId.containsKey(loginId)) {//已经登录过

            //判断是否同一个IP
            if (allUserId.get(loginId).getClientIp().equalsIgnoreCase(clientIp)) {
                System.out.println("同一IP下重新登录");
                sendClose(allUserId.get(loginId).getCon());//告诉原来的连接关闭页面

                allUserId.get(loginId).setCon(chc);//重新设置连接
            } else {
                System.out.println("不同IP下重登录");
                // 在不同的地方登录
                sendRepeat(allUserId.get(loginId).getCon());//告诉原来的连接在其他地方登录

                allUserId.get(loginId).setCon(chc);//重新设置连接

                allUserId.get(loginId).setClientIp(clientIp);//重新设置IP
                allUserId.get(loginId).setName(username);
            }

        } else {
            //没有登录过的用户            
            client.setLoginId(loginId);
            client.setClientIp(clientIp);
            client.setCon(chc);
            client.setName(username);
            allUserId.put(loginId, client);

        }
        sayToAll();

    }

    public void sayToAll() {

        getAllUser();
        Message msg = new Message();
        msg.setType("users");
        msg.setBody(gson.toJson(userList));
        for (String key : allUserId.keySet()) {

            send(allUserId.get(key).getCon(), gson.toJson(msg));
        }
    }

    public void sayToAllMsg(Message msg) {
        try {
            getAllUser();

            for (String key : allUserId.keySet()) {

                send(allUserId.get(key).getCon(), gson.toJson(msg));
            }
        } catch (Exception e) {
        }
    }

    private void sayToAllOffline(String loginId) {

        getAllUser();
        Message msg = new Message();
        msg.setType("offline");
        msg.setBody(loginId);
        //msg.setBody(gson.toJson(userList));
        for (String key : allUserId.keySet()) {

            send(allUserId.get(key).getCon(), gson.toJson(msg));
        }
    }

    private List getAllUser() {
        try {
            WebClient cli = null;
            userList = new ArrayList<WebClient>();
            for (String key : allUserId.keySet()) {
                cli = allUserId.get(key).clone();
                cli.setCon(null);

                userList.add(cli);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return userList;

    }

    private void removeUser(String loginId) {
        try {
            allUserId.get(loginId).getCon().getChannel().close();
        } catch (Exception e) {

        }
        allUserId.remove(loginId);
    }

    public void sendClose(ChannelHandlerContext chc) {
        try {
            //  send(chc, "{\"type\":\"" + Type.CLOSE + "\"}");
            chc.getChannel().close();
        } catch (Exception e) {
            // e.printStackTrace();
        }

    }

    public void sendRepeat(ChannelHandlerContext chc) {
        try {
            send(chc, "{\"type\":\"" + Type.REPEAT + "\"}");
            // chc.getChannel().close();
        } catch (Exception e) {
            //e.printStackTrace();
        }

    }

    public BlockingQueue getSendQueue() {
//        if (sendMessageQueue == null) {
//            new LinkedBlockingQueue<Message>();
//        }
        return sendMessageQueue;
    }

    public static void main(String[] args) {
        StartServer server = new StartServer(19090);
        server.init();
    }
}
